/**
 * @InitView.as
 * 
 * @author sodaChen mail:asframe@163.com
 * @version 1.0
 * <br>Copyright (C), 2010 asFrame.com
 * <br>This program is protected by copyright laws.
 * <br>Program Name:AStruts2
 * <br>Date:2012-4-16
 */
package com.asframe.astruts2.controller
{
	import com.asframe.astruts2.AStruts2Utils;
	import com.asframe.astruts2.beans.MediatorBean;
	import com.asframe.astruts2.beans.ViewBean;
	import com.asframe.astruts2.context.AStrutsData;
	import com.asframe.astruts2.context.IAStrutsContext;
	import com.asframe.astruts2.errors.AStrutsError;
	import com.asframe.astruts2.event.InitViewMediatorEvent;
	import com.asframe.astruts2.interfaces.IInitViewEnd;
	import com.asframe.astruts2.interfaces.IMediatorCreateEvent;
	import com.asframe.astruts2.interfaces.IView;
	import com.asframe.astruts2.interfaces.IViewCreateEvent;
	import com.asframe.astruts2.interfaces.IViewHandler;
	import com.asframe.astruts2.metadata.MetadataConst;
	import com.asframe.astruts2.proxy.MethodobserverProxy;
	import com.asframe.collections.lists.IList;
	import com.asframe.load.multi.SameLoader;
	import com.asframe.pattern.observer.IObserver;
	import com.asframe.ref.Arg;
	import com.asframe.ref.Metadata;
	import com.asframe.ref.Method;
	import com.asframe.ref.Type;
	import com.asframe.ref.Variable;
	import com.asframe.slf4j.ILogger;
	import com.asframe.slf4j.LoggerFactory;
	import com.asframe.utils.RefUtils;
	
	import flash.display.Sprite;
	import flash.events.EventDispatcher;
	
	/**
	 * 初始化一个显示对象
	 * @author sodaChen
	 * @Date:2012-4-16
	 */
	public class InitViewMediator extends EventDispatcher
	{
		private static var log				:ILogger = LoggerFactory.getLogger(InitViewMediator);
		private var viewBean				:ViewBean;
		private var viewHandlerList			:IList;
		private var astrutsInit				:AStrutsData;
		private var context					:IAStrutsContext;
		private var isInit					:Boolean;
		
		/**
		 * 初始化ViewBean的配置信息，实例化View和Mediator
		 * @param viewBean
		 * @param astrutsInit
		 * @param complete
		 * @param isInit
		 * 
		 */		
		public function InitViewMediator( viewBean:ViewBean, astrutsInit:AStrutsData, isInit:Boolean = false)
		{
			this.viewBean = viewBean;
			this.astrutsInit = astrutsInit;
			this.context = astrutsInit.context;
		}
		/**
		 * 初始化View和Mediator
		 */		
		public function initViewMediator():void
		{
			if(viewBean.reses != null && viewBean.reses.length > 0)
			{
				if(astrutsInit.loader == null)
				{
					var sameLoader:SameLoader = new SameLoader();
					sameLoader.setNextLoader(new ResNextLoader());
					astrutsInit.loader = sameLoader;
				}
				//进行资源加载
				astrutsInit.loader.load(viewBean.reses,
										function(results:Array):void
										{
											handleViewMediator();
										},
										astrutsInit.loading);
			}
			else
			{
				handleViewMediator();
			}
		}
		private function handleViewMediator():void
		{
			var view:* = null;
			var mediatorBeans:Array = viewBean.mediators;
			if(viewBean.type == null)
			{
				if(viewBean.clazz.length == 1)
				{
					if(viewBean.clazz != ".")
					{
						throw new AStrutsError(viewBean + "初始化错误，必须有类路径或者为 . " );
					}
					view = astrutsInit.root;
				}
				else
				{
					try
					{
						view = RefUtils.refObject(viewBean.clazz);
					} 
					catch(error:Error) 
					{
						throw new AStrutsError(viewBean.clazz + "不能反射出实例:" + 
							error.getStackTrace());
					}
				}
			}
			else
			{
				view =  new viewBean.type.clazz();
			}
			initViewContainer(view,viewBean);
//			if(astrutsInit.viewCreateEvents != null)
//			{
//				//处理view的创建事件
//				for each (var viewCreateEvent:IViewCreateEvent in astrutsInit.viewCreateEvents) 
//				{
//					if(viewCreateEvent.isTally(view))
//					{
//						//初始化view,这里应该同时初始化view相关的Mediaor
//						viewCreateEvent.viewCreateEvent(view,viewBean,astrutsInit);
//					}
//				}
//			}
			//执行对view的一些操作
			if(astrutsInit.viewHandlers != null)
			{
				for each (var viewHandler:IViewHandler in astrutsInit.viewHandlers) 
				{
					viewHandler.setAStrutsData(astrutsInit);
					viewHandler.addView(viewBean);
				}
			}
			//添加到view容器中
			astrutsInit.root.getViewContainer().addChild(viewBean.viewContainer);
			
			var mediator:* = null;
			var mediatorType:Type = null;
			for each (var mediatorBean:MediatorBean in mediatorBeans) 
			{
				mediatorType = mediatorBean.mediatorType;
				if(mediatorType == null)
				{
					mediatorType = Type.forName(mediatorBean.clazz);
				}
				mediator = new mediatorType.clazz();
				mediatorBean.mediator = mediator;
				//执行标签
				AStruts2Utils.setContext(mediator,context);
				//如果中介有view名称的属性，则直接进行复制(支持约定约定)
				if(astrutsInit.systemBean.convention && mediator.hasOwnProperty(viewBean.name))
				{
					try
					{
						mediator[viewBean.name] = view;
					}
					catch(error:Error)
					{
						log.error(mediator + "执行Mediator进行约定的设置view出现错误，约定名称" + viewBean.name,error);	
					}
				}
				//进行相关的元数据处理
				astrutsInit.injector.injection(mediator,mediatorType,context);
				//放到容器中
				context.registerBean(mediator,mediatorBean.name);
				var metadata:Metadata = null;
				var noticeKey:* = null
				//增加感兴趣的通知的注册,主要是进行标签处理之类的,查看是否有监听的方法
				for each (var variable:Variable in mediatorType.staticConstants) 
				{
					//查看是否有Notice标签
					metadata = variable.getMetadata(MetadataConst.NOTICE_METADATA);
					if(metadata != null)
					{
						//获取到静态常量的值
						noticeKey = variable.getValue();
						//开启约定，并且有对应的方法
						if(astrutsInit.systemBean.convention && mediator.hasOwnProperty(noticeKey))
						{
							addObserver(mediatorBean,noticeKey,new MethodobserverProxy(mediatorBean,mediator[noticeKey]));
						}
						else
						{
							//
							addObserver(mediatorBean,noticeKey,mediator as IObserver);
						}
					}
				}
				var methodProxy:MethodobserverProxy = null;
				var arg:Arg = null;
				//处理是否有方法作为Notice的
				for each (var method:Method in mediatorType.methods) 
				{
					metadata = method.getMetadata(MetadataConst.NOTICE_METADATA);
					if(metadata != null)
					{
						methodProxy = new MethodobserverProxy(mediator,mediator[method.name]);
						arg = metadata.firestArg;
						if(arg != null)
						{
							addObserver(mediatorBean,arg.value,methodProxy);
						}
						else
						{
							addObserver(mediatorBean,method.name,methodProxy);
						}
					}
				}
				//配置文件中指定的主题
				for each (var noticeStr:String in mediatorBean.notices) 
				{
					//开启约定，并且有对应的方法
					if(astrutsInit.systemBean.convention && mediator.hasOwnProperty(noticeStr))
					{
						addObserver(mediatorBean,noticeStr,new MethodobserverProxy(mediatorBean,mediator[noticeStr]));
					}
					else
					{
						addObserver(mediatorBean,noticeStr,mediator as IObserver);
					}
				}
				//Mediator创建事件
//				for each (var mediatoEvent:IMediatorCreateEvent in astrutsInit.mediatorCreateEvents) 
//				{
//					//进行mediator的后续事件处理
//					if(mediatoEvent.isTally(mediator))
//					{
//						mediatoEvent.mediatorCreateEvent(view,mediator,mediatorBean,context);
//					}
//				}
			}
			for each (var initViewEnd:IInitViewEnd in astrutsInit.initViewEnds) 
			{
				try
				{
					initViewEnd.initViewEnd(viewBean);
				}
				catch(error:Error)
				{
					log.error("调用IInitViewEnd接口时发生错误.",error.getStackTrace());
				}
			}
			dispatchEvent(new InitViewMediatorEvent(InitViewMediatorEvent.INIT_OVER,viewBean));
		}
		/**
		 * 初始化view的容器(子类可以扩展获取到view容器的方式)
		 * @param view
		 * @param viewBean
		 */		
		protected function initViewContainer(view:*,viewBean:ViewBean):void
		{
			viewBean.view = view;
			//如果view本身是个显示对象，那么它一定也是view本身的容器了
			if(view is Sprite)
			{
				viewBean.viewContainer = view;
			}
			else if(view is IView)
			{
				//处理view接口
				viewBean.viewContainer = IView(view).getContainer();
			}
			else
			{
				//有getContainer和getViewContainer的方法也行
				setViewContainer(view,viewBean,"getContainer");
				if(viewBean.viewContainer == null)
				{
					setViewContainer(view,viewBean,"getViewContainer");
				}
			}
			if(viewBean.viewContainer == null)
			{
				//到现在还没有view容器，则抛出错误了
				throw new AStrutsError(view + "找不到viewContainer容器。请注意view本身是否为sprie或者其子类"
				+ "或者实现了IView接口，又或者具备getContainer和getViewContainer方法");
			}
		}
		private function setViewContainer(view:*,viewBean:ViewBean,methodName:String):void
		{
			var container:Sprite = RefUtils.invokeMethod(view,methodName,viewBean.type);
			if(container != null)
			{
				viewBean.viewContainer = container;
			}
		}
		/**
		 * 添加一个观察者 
		 * @param mediatorBean Mediator的数据
		 * @param notice 通知
		 * @param observer 观察者
		 * 
		 */		
		private function addObserver(mediatorBean:MediatorBean,notice:*,observer:IObserver):void
		{
			astrutsInit.subjects.addObserver(notice, observer);
			mediatorBean.addObserver(notice,observer);
		}
	}
}
